﻿using UnityEngine;
using System.Collections.Generic;
using Data;
using UnityEditor;
using System.IO;
using System;



public class TPFrameData
{
    public string name;
    public Rect frame;
    public Vector2 offset;
    public bool rotated;
    public Rect sourceColorRect;
    public Vector2 sourceSize;

    public void LoadX(string sname, PList plist)
    {
        name = sname;
        //frame = TPAtlas.StrToRect(plist["frame"] as string);
        //offset = TPAtlas.StrToVec2(plist["offset"] as string);
        //sourceColorRect = TPAtlas.StrToRect(plist["sourceColorRect"] as string);
        //sourceSize = TPAtlas.StrToVec2(plist["sourceSize"] as string);
        object varCheck;
        if (plist.TryGetValue("frame", out varCheck))
        {
            frame = TPAtlas.StrToRect(plist["frame"] as string);
            offset = TPAtlas.StrToVec2(plist["offset"] as string);
            rotated = Convert.ToBoolean(plist["rotated"] as string);
            sourceColorRect = TPAtlas.StrToRect(plist["sourceColorRect"] as string);
            sourceSize = TPAtlas.StrToVec2(plist["sourceSize"] as string);
        }
        else
        {
            frame = TPAtlas.StrToRect(plist["textureRect"] as string);
            offset = TPAtlas.StrToVec2(plist["spriteOffset"] as string);
            sourceColorRect = TPAtlas.StrToRect(plist["sourceColorRect"] as string);
            sourceSize = TPAtlas.StrToVec2(plist["spriteSourceSize"] as string);
        }
    }
}



public class TPAtlas
{
    public string realTextureFileName;
    public Vector2 size;
    public List<TPFrameData> sheets = new List<TPFrameData>();

    public void LoadX(PList plist)
    {
        //read metadata
        PList meta = plist["metadata"] as PList;
        object varCheck;
        if (meta.TryGetValue("realTextureFileName", out varCheck))
        {
            realTextureFileName = meta["realTextureFileName"] as string;
        }
        else
        {
            PList ptarget = meta["target"] as PList;
            realTextureFileName = ptarget["name"] as string;
        }

        size = StrToVec2(meta["size"] as string);

        //read frames
        PList frames = plist["frames"] as PList;
        foreach (var kv in frames)
        {
            string name = kv.Key;
            PList framedata = kv.Value as PList;
            TPFrameData frame = new TPFrameData();
            frame.LoadX(name, framedata);
            sheets.Add(frame);
        }
    }

    public static Vector2 StrToVec2(string str)
    {

        str = str.Replace("{", "");
        str = str.Replace("}", "");
        string[] vs = str.Split(',');

        Vector2 v = new Vector2();
        v.x = float.Parse(vs[0]);
        v.y = float.Parse(vs[1]);
        return v;
    }

    public static Rect StrToRect(string str)
    {
        str = str.Replace("{", "");
        str = str.Replace("}", "");
        string[] vs = str.Split(',');

        Rect v = new Rect(float.Parse(vs[0]), float.Parse(vs[1]), float.Parse(vs[2]), float.Parse(vs[3]));
        return v;
    }
}



public class SpriteSheetConvert : ScriptableObject
{
    public static string GetUTF8String(byte[] bt)
    {
        string val = System.Text.Encoding.UTF8.GetString(bt);
        return val;
    }

    //[MenuItem("Assets/Texture1/PLisToSprites(SelectPList)")]
    public static void ConvertSprite()
    {
        //EditorUtility.DisplayDialog("MyTool", "Do It in C# !", "OK", "");
        var selobj = Selection.activeObject;
        string selectionPath = AssetDatabase.GetAssetPath(Selection.activeObject);
        if (!selectionPath.EndsWith(".plist"))
        {
            EditorUtility.DisplayDialog("Error", "Please select a plist file!", "OK", "");
            return;
        }

        Debug.LogWarning("#PLisToSprites start:" + selectionPath);
        string fileContent = string.Empty;
        using (FileStream file = new FileStream(selectionPath, FileMode.Open))
        {
            byte[] str = new byte[(int)file.Length];
            file.Read(str, 0, str.Length);
            fileContent = GetUTF8String(str);
            Debug.Log(fileContent);
            file.Close();
            file.Dispose();
        }
        //去掉<!DOCTYPE>,不然异常
        int delStart = fileContent.IndexOf("<!DOCTYPE");
        int delEnd = fileContent.IndexOf("\n", delStart);
        fileContent = fileContent.Remove(delStart, delEnd - delStart);
        Debug.Log(fileContent);
        //解析文件
        PList plist = new PList();
        plist.LoadText(fileContent);//Load(selectionPath);
        TPAtlas at = new TPAtlas();
        at.LoadX(plist);

        //重写meta
        string texPath = Path.GetDirectoryName(selectionPath) + "/" + System.IO.Path.GetFileName(at.realTextureFileName);
        Texture2D selTex = AssetDatabase.LoadAssetAtPath(texPath, typeof(Texture2D)) as Texture2D;
        Debug.Log("texture:" + texPath);
        Debug.Log("write texture:" + selTex.name + "  size:" + selTex.texelSize);
        TextureImporter textureImporter = AssetImporter.GetAtPath(texPath) as TextureImporter;

        /*if (textureImporter.textureType != TextureImporterType.Sprite && textureImporter.textureType != TextureImporterType.Default)
        {
            EditorUtility.DisplayDialog("Error", "Texture'type must be sprite or Advanced!", "OK", "");
            return;
        }
        if (textureImporter.spriteImportMode != SpriteImportMode.Multiple)
        {
            EditorUtility.DisplayDialog("Error", "spriteImportMode must be Multiple!", "OK", "");
            return;
        }*/

        textureImporter.textureType = TextureImporterType.Sprite;
        AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate);
        AssetDatabase.Refresh();

        //注意：SpriteMetaData 不支持旋转
        //https://www.cnblogs.com/twjcnblog/p/6052169.html
        //https://www.cnblogs.com/NGZ3D/p/10006336.html
        SpriteMetaData[] sheetMetas = new SpriteMetaData[at.sheets.Count];
        for (int i = 0; i < at.sheets.Count; i++)
        {
            TPFrameData frameData = at.sheets[i];

            sheetMetas[i].alignment = 0;
            sheetMetas[i].border = new Vector4(0, 0, 0, 0);
            sheetMetas[i].name = frameData.name;
            sheetMetas[i].pivot = new Vector2(0.5f, 0.5f);

            float x = -1.0f;
            float y = -1.0f;
            float width = -1.0f;
            float height = -1.0f;
            //旋转时, 采样宽高调换
            if (frameData.rotated)
            {
                //x = frameData.frame.y;
                //y = at.size.x - frameData.frame.x - frameData.frame.width;

                width = frameData.frame.height;
                height = frameData.frame.width;
            }
            else
            {
                x = frameData.frame.x;
                y = at.size.y - frameData.frame.y - frameData.frame.height;

                width = frameData.frame.width;
                height = frameData.frame.height;
            }
            sheetMetas[i].rect = new Rect(x, y, width, height);

            //sheetMetas[i].rect = new Rect(frameData.frame.x, at.size.y - frameData.frame.y - frameData.frame.height,
            //frameData.frame.width, frameData.frame.height);//这里原点在左下角，y相反
            //Debug.Log("do sprite:" + frameData.name);
        }
        //textureImporter.spriteImportMode = SpriteImportMode.Multiple;
        textureImporter.spritesheet = sheetMetas;

        //save
        textureImporter.textureType = TextureImporterType.Sprite;       //bug?
        textureImporter.spriteImportMode = SpriteImportMode.Multiple;   //不加这两句会导致无法保存meta
        AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate);

        Debug.LogWarning("#PLisToSprites end:" + texPath);
    }
}
